library(palmerpenguins)
library(tidyverse)RAdelaide 2025
July 8, 2025
IntroVisualisation.RR comes with some very powerful plotting capabilities
graphicsggplot2 changed everythingcars dataset
speed (mph)dist (ft) each car takes to stopboxplot() can also create simple figures easilyy ~ x \(\implies\) y depends on xpairs()ggplot2ggplot2 has become the industry standard for visualisation (Wickham 2016)tidyverseTaken from https://r.qcbs.ca/workshop03/book-en/grammar-of-graphics-gg-basics.html
Everything is added in layers
tibble)x & y co-ordinatescolour, fill, shape, size, linetypealpha)carsspeed (mph)distance each car takes to stopx vs y plot using pointsspeeddistancex & ygeom_point() after calling ggplot()+ after ggplot() says “But wait! There’s more…”ggplot2 was created neither pipe had been developed yetgeom_point() after calling ggplot()
+ after ggplot() says “But wait! There’s more…”stat_smooth()
What visualisations could we produce to inspect penguins?
se = FALSE and see what happensggplot() \(\implies\) all layers will use thiscolour = species to geom_point() \(\implies\) ???~ notation to say all facets depend on speciesggplot2 will detect the most appropriate scale
scale_x_continuous() and scale_y_continuous()scale_x_log10(), scale_x_sqrt(), scale_x_reverse()yscale_colour_discrete() (Meh…)scale_colour_brewer(), scale_colour_viridis_d()scale_colour_brewer() \(\implies\) RColorBrewer::display.brewer.all()scale_colour_viridis_d() will give a colourblind-friendly palette
ggthemes (Wong 2011)
sex will have missing values## Try setting different point shapes based on the recorded sex
penguins |>
filter(!is.na(sex)) |> # Remove the penguins with unrecorded sex
ggplot(aes(x = bill_depth_mm, y = bill_length_mm, colour = species)) +
geom_point(aes(shape = sex)) + # Now we have a layer-specific aesthetic
stat_smooth(method = "lm", se = FALSE) +
scale_colour_colorblind()## Try setting different point shapes based on the recorded sex
penguins |>
filter(!is.na(sex)) |> # Remove the penguins with unrecorded sex
ggplot(aes(x = bill_depth_mm, y = bill_length_mm, colour = species)) +
geom_point(aes(shape = sex), size = 3) + # Change the point size
stat_smooth(method = "lm", se = FALSE) +
scale_colour_colorblind()scale_shape_manual()
scale_colour_manual()## Try setting different point shapes based on the recorded sex
penguins |>
filter(!is.na(sex)) |> # Remove the penguins with unrecorded sex
ggplot(aes(x = bill_depth_mm, y = bill_length_mm, colour = species)) +
geom_point(aes(shape = sex), size = 3) +
stat_smooth(method = "lm", se = FALSE) +
scale_colour_colorblind() +
scale_shape_manual(values = c(19, 1)) ## Manually choose the point shapes?pch and scroll down a little
## Try setting different point shapes based on the recorded sex
penguins |>
filter(!is.na(sex)) |> # Remove the penguins with unrecorded sex
ggplot(aes(x = bill_depth_mm, y = bill_length_mm, colour = species)) +
geom_point(aes(shape = sex), size = 3) +
stat_smooth(method = "lm", se = FALSE) +
scale_colour_colorblind() +
scale_shape_manual(values = c(19, 1)) +
labs(
# Manually add labels
x = "Bill Depth (mm)", y = "Bill Length (mm)",
colour = "Species", shape = "Sex"
) p
## Save the figure for exploring theme attributes
p <- penguins |>
filter(!is.na(sex)) |> # Remove the penguins with unrecorded sex
ggplot(aes(x = bill_depth_mm, y = bill_length_mm, colour = species)) +
geom_point(aes(shape = sex), size = 3) +
stat_smooth(method = "lm", se = FALSE) +
scale_colour_colorblind() +
scale_shape_manual(values = c(19, 1)) +
labs(
x = "Bill Depth (mm)", y = "Bill Length (mm)",
colour = "Species", shape = "Sex"
) theme_grey()theme_bw()
legend.position = "inside"element_text()?theme \(\implies\) 4 main types of ‘element’element_text()
element_line()
element_rect()
element_blank()
# Make the most horrible figure possible
p + theme_bw() +
theme(
## A slightly exaggerated modification of axis titles
axis.title = element_text(colour = "darkred", size = 16, face = "bold"),
## Make axes thick, blue lines. Ewww
axis.line = element_line(colour = "darkblue", linewidth = 2),
## Hide the underlying grid
panel.grid = element_blank(),
## Make the area background a light grey
plot.background = element_rect(fill = "grey70")
)geom_bar() & geom_col()geom_errorbar() & geom_errorbarh()geom_boxplot() & geom_violin()geom_density() & geom_histogram()geom_line(), geom_segment()geom_abline(), geom_hline() & geom_vline()geom_raster(), geom_tile() & geom_rect()sex as the predictorbody_mass_g may be a response variablecolour is generally applied to shape outlinesggplot2 will always separate multiple values/categoryfacet_wrap()facet_grid()) will allow for unequal-sized facetsgeom_jitter() will draw points but with noise in either directionalpha parameter will make the points partially transparenttrim = FALSE)ggplot2 is a bit uglyfill = "grey70" and colour = "black"binwidth is automatically set \(\implies\) try binwidth = 100# A tibble: 6 × 4
species sex weight_mn weight_sd
<fct> <fct> <dbl> <dbl>
1 Adelie male 4043. 347.
2 Adelie female 3369. 269.
3 Gentoo female 4680. 282.
4 Gentoo male 5485. 313.
5 Chinstrap female 3527. 285.
6 Chinstrap male 3939. 362.
geom_col()## Begin creating a bar plot, with separate panels for each species
penguins |>
filter(!is.na(sex)) |>
summarise(
weight_mn = mean(body_mass_g, na.rm = TRUE),
weight_sd = sd(body_mass_g, na.rm = TRUE),
.by = c(species, sex)
) |>
ggplot(aes(sex, weight_mn, fill = sex)) +
geom_col() +
facet_wrap(~species, nrow = 1) penguins |>
filter(!is.na(sex)) |>
summarise(
weight_mn = mean(body_mass_g, na.rm = TRUE),
weight_sd = sd(body_mass_g, na.rm = TRUE),
.by = c(species, sex)
) |>
ggplot(aes(sex, weight_mn, fill = sex)) +
geom_col() +
## Now add error bars adding/subtracting from the mean 'on the fly'
geom_errorbar(
aes(ymin = weight_mn - weight_sd, ymax = weight_mn + weight_sd),
width = 0.2 # Set the width of tails on the error bars
) +
facet_wrap(~species, nrow = 1) +
## Some extra code to make the plot look great
scale_y_continuous(expand = expansion(c(0, 0.05))) +
scale_fill_brewer(palette = "Set1") +
theme_bw()geom_text() will overlay labels exactly on the pointsgeom_text_repel() will shift labels marginally away from the pointsgeom_label() and geom_label_repel() will add borders and fill to labelsExport in the Plots paneA fabulous resource: https://r-graphics.org/
stat_ellipse() to your plot